package pwd.allen.password;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * 基于 spel表达式解析器 实现校验
 *
 * @author 门那粒沙
 * @create 2021-12-19 14:26
 **/
public class SpelCheckRule implements ICheckRule {

    private static final Logger logger = LoggerFactory.getLogger(SpelCheckRule.class);

    private List<Condition> conds = new ArrayList<>();
    private Class<PasswordUtil> utilClassType = PasswordUtil.class;

    private SpelExpressionParser parser = new SpelExpressionParser();

    /**
     * 最低要满足的的规则
     */
    private List<Condition> constantConds = new ArrayList<>();
    {
        // 内置密码规则 TODO
        constantConds.add(new Condition("matchAtLeast(2,REGEX_CONTAIN_DIGIT,REGEX_CONTAIN_LETTER)", "必须包含数字和字母"));
        constantConds.add(new Condition("lengthLT(6)", "最低6位字符"));
    }

    @Override
    public CheckMsg check(String password) {
        if (conds == null || conds.isEmpty()) {
            return new CheckMsg(CheckMsg.Type.ERROR, "配置不能为空");
        }
        if (password == null) {
            password = "";
        }
        try {
            StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
            PasswordUtil passwordUtil = utilClassType.newInstance();
            passwordUtil.setPassword(password);
            evaluationContext.setRootObject(passwordUtil);

            //<editor-fold desc="逐个执行条件表达式进行验证">
            for (Condition cond : conds) {
                Expression expression = parser.parseExpression(cond.getCond());
                if (!expression.getValue(evaluationContext, boolean.class)) {
                    return new CheckMsg(CheckMsg.Type.NOPASS, cond.getMsg());
                }
            }
            for (Condition cond : constantConds) {
                Expression expression = parser.parseExpression(cond.getCond());
                if (!expression.getValue(evaluationContext, boolean.class)) {
                    return new CheckMsg(CheckMsg.Type.NOPASS, cond.getMsg());
                }
            }
            //</editor-fold>
        } catch (Exception e) {
            logger.error(e.toString(), e);
            return new CheckMsg(CheckMsg.Type.ERROR, e.toString());
        }
        return new CheckMsg(CheckMsg.Type.PASS, "验证通过");
    }

    public List<Condition> getConds() {
        return conds;
    }

    public void setConds(List<Condition> conds) {
        this.conds = conds;
    }

    public void setUtilClassType(Class<PasswordUtil> utilClassType) {
        this.utilClassType = utilClassType;
    }
}
